home *** CD-ROM | disk | FTP | other *** search
- /*
- * Beispiel-Programm zur Benutzung des Selectric-Protokolls mit BoxKite
- * unter MiNT/MultiTOS/MagiC/MagiC Mac
- * (c) Harald Becker, 12.5.1994. Übersetzt mit Pure C und DEFAULT.PRJ.
- *
- * Diesen Code dürfen Sie nach Belieben verwenden und ganz oder in in Auszügen
- * in Ihre Programme aufnehmen.
- *
- * HB 061095:
- * Erweitert um eine Anwendung für den Message-Callback in BoxKite 1.7x
- * Dazu wird hinter dem Fileselector ein kleines Fenster geöffnet,
- * das über den Message-Callback gezeichnet wird. Es kann auch
- * verschoben werden, falls das Betriebssystem das Verschieben hinten-
- * liegender Fenster erlaubt.
- *
- * HB 131095:
- * Inzwischen demonstriert das Programm alle drei möglichen Rückgabeformen.
- * Die Auswahl erfolgt zur Compile-Zeit über die Konstante 'RETURN'.
- */
- #include <stdio.h>
- #include <aes.h>
- #include <tos.h>
- #include <string.h>
-
- /*
- * Diese Konstante steuert, welche Rückgabemethode das Beispielprogramm
- * bei BoxKite anfordert. Mögliche Werte:
- *
- * 1: Rückgabe über ein Feld von Stringzeigern
- * 2: Rückgabe über einen String (mit trennenden Leerzeichen)
- * 3: Rückgabe über Funktionen
- */
- #define RETURN 1
-
- /*
- * Diese Struktur wird von BoxKite gefüllt. Sie ist identisch mit der
- * TOS-DTA, sieht jedoch Platz für lange Datenamen vor.
- */
- typedef struct
- { char d_reserved[21];
- unsigned char d_attrib;
- unsigned int d_time;
- unsigned int d_date;
- unsigned long d_length;
- char d_fname[34];
- } XDTA;
-
- /*
- * Die Selectric-Struktur.
- */
- typedef struct
- { unsigned long id; /* Selectric ID (SLCT) */
- unsigned int version; /* version (BCD-Format) */
- struct
- { unsigned : 7; /* reserved */
- unsigned pthsav : 1;
- unsigned stdest : 1;
- unsigned : 1;
- unsigned numsrt : 1; /* numerisches Sortieren */
- unsigned lower : 1;
- unsigned dclick : 1; /* Ordner mit Doppelklick */
- unsigned hidden : 1; /* versteckte Dateien */
- unsigned onoff : 1; /* Fileselector AN/AUS */
- } config;
- int sort; /* sort-mode (neg. = rev.) */
- int num_ext; /* number of extensions */
- char *(*ext)[]; /* preset extensions */
- int num_paths; /* number of paths */
- char *(*paths)[]; /* preset paths */
- int comm; /* communication word */
- int in_count; /* input counter */
- void *in_ptr; /* input pointer */
- int out_count; /* output counter */
- void *out_ptr; /* output pointer */
- int cdecl (*get_first)(XDTA *dta, int attrib);
- int cdecl (*get_next)(XDTA *dta);
- int cdecl (*release_dir)(void);
- } SLCT_STR;
-
- typedef struct
- { long id;
- long value;
- } COOKIE;
-
- long Supexec(long (*codeptr)());
-
- SLCT_STR *slct_cookie;
-
- /*
- * Prototyp des Message-Handlers.
- */
- typedef void cdecl (* FSEL_CALLBACK)(int *msg);
-
- /*
- * Prototyp des erweiterten Bindings.
- */
- int cdecl fsel_boxinput(char *path, char *name, int *button, char *label, FSEL_CALLBACK callback);
-
- /*
- * Variablen für die Rückgabe der Dateinamen.
- */
- #if RETURN == 1
- char name1[34], name2[34], name3[34];
- char *nameptrs[] = { name1, name2, name3 };
- #elif RETURN == 2
- char stringbuf[256];
- #else
- int cdecl (*p_get_first)(XDTA *dta, int attrib);
- int cdecl (*p_get_next)(XDTA *dta);
- int cdecl (*p_release_dir)(void);
- #endif
-
- int name_count; /* Anzahl der gelieferten Namen */
-
- int window; /* Fensterkennung */
- OBJECT contents = /* Fensterinhalt */
- { -1, -1, -1, G_BOXCHAR, 0, 0, 0x2aff11f0, 1, 1, 1, 1 };
-
- int xdesk, ydesk, wdesk, hdesk;
-
- /*
- * Gibt die Adresse des Cookie-Jar zurück. Mit Supexec() aufrufen.
- */
- long get_cookiejar(void)
- { return *((long *)0x05a0l);
- }
-
- /*
- * Durchsucht den Cookie Jar nach einem cookie mit gegebener id und
- * liefert dessen Wert zurück.
- */
- long get_cookie(long id)
- { long sav;
- COOKIE *cookiejar;
- int i = 0;
-
- cookiejar = (COOKIE *)Supexec(get_cookiejar);
-
- if ( cookiejar )
- { while ( cookiejar[i].id )
- { if ( cookiejar[i].id == id )
- return cookiejar[i].value;
- i++;
- }
- }
- return 0L;
- }
-
- /*
- * Prüft, ob am 'FSEL'-cookie ein Selectric-1.02-kompatibler Fileselector
- * hängt. Im Erfolgsfall wird die Datenstruktur hinter dem Cookie für die
- * gewünschte Rückgabeform initialisiert.
- * Sollte mit Supexec aufgerufen werden, da der Speicher immerhin einem
- * fremden Prozeß gehört.
- */
- long setup_selector(void)
- { if ( slct_cookie && slct_cookie->id == 'SLCT' && slct_cookie->version >= 0x102 )
- {
- #if RETURN == 1
- slct_cookie->comm = 1;
- slct_cookie->out_count = 3;
- slct_cookie->out_ptr = nameptrs;
- #elif RETURN == 2
- slct_cookie->comm = 3;
- slct_cookie->out_count = 5;
- slct_cookie->out_ptr = stringbuf;
- #else
- slct_cookie->comm = 9;
- p_get_first = slct_cookie->get_first;
- p_get_next = slct_cookie->get_next;
- p_release_dir = slct_cookie->release_dir;
-
- #endif
- return 1;
- }
- return 0;
- }
-
- /*
- * Liest die Anzahl der gelieferten Namen aus der FSEL-Struktur.
- */
- long get_out_count(void)
- { name_count = slct_cookie->out_count;
- return 0;
- }
-
- /*
- * Fragt das aktuelle Laufwerk und den aktuellen Pfad ab.
- */
- void getpath(char *p)
- { int drv;
-
- drv = Dgetdrv();
- *p++ = drv + 'A';
- *p++ = ':';
- Dgetpath(p, drv);
- p += strlen(p) - 1;
- if ( *p != '\\' )
- { p++;
- *p++ = '\\';
- *p = 0;
- }
- }
-
- /*
- * Die folgenden vier Funktionen befassen sich nur mit dem Zeichnen
- * des Fensterinhaltes. Ich denke, die Methode hat sich inzwischen
- * herumgesprochen.
- */
- int min(int a, int b)
- { return ( a < b ? a : b );
- }
-
- int max(int a, int b)
- { return ( a > b ? a : b );
- }
-
- int rc_intersect(GRECT *p1, GRECT *p2)
- { int tx, ty, tw, th;
-
- tw = min(p2->g_x + p2->g_w, p1->g_x + p1->g_w);
- th = min(p2->g_y + p2->g_h, p1->g_y + p1->g_h);
- tx = max(p2->g_x, p1->g_x);
- ty = max(p2->g_y, p1->g_y);
-
- p2->g_x = tx;
- p2->g_y = ty;
- p2->g_w = tw - tx;
- p2->g_h = th - ty;
-
- return( (tw > tx) && (th > ty) );
- }
-
- void window_redraw(int handle, int x, int y, int w, int h)
- { GRECT r1, r2, world;
-
- wind_update(BEG_UPDATE);
-
- r2.g_x = x;
- r2.g_y = y;
- r2.g_w = w;
- r2.g_h = h;
-
- world.g_x = xdesk;
- world.g_y = ydesk;
- world.g_w = wdesk;
- world.g_h = hdesk;
-
- wind_get(handle, WF_FIRSTXYWH, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);
- while ( r1.g_w && r1.g_h )
- { if ( rc_intersect(&world, &r1) && rc_intersect(&r2, &r1) )
- objc_draw(&contents, ROOT, MAX_DEPTH, r1.g_x, r1.g_y, r1.g_w, r1.g_h);
- wind_get(handle, WF_NEXTXYWH, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);
- }
- wind_update(END_UPDATE);
- }
-
- /*
- * Die Einsprungadresse dieser Funktion wird als Callback an BoxKite
- * übergeben.
- */
- void cdecl message_handler(int *msg)
- { switch ( msg[0] )
- { case WM_REDRAW:
- wind_get(msg[3], WF_WORKXYWH, &contents.ob_x, &contents.ob_y, &contents.ob_width, &contents.ob_height);
- window_redraw(msg[3], msg[4], msg[5], msg[6], msg[7]);
- break;
- case WM_MOVED:
- wind_set(msg[3], WF_CURRXYWH, msg[4], msg[5], msg[6], msg[7]);
- break;
- }
- }
-
- /*
- * Ein alternatives Binding für fsel_exinput() (Die Funktionsnummer ist
- * identisch!), das die Übergabe der Callback-Adresse erlaubt. Andere
- * Fileselectoren sollten den überzähligen Parameter einfach ignorieren.
- *
- * Eine Assembler-Version dieses Bindings, die keine Annahmen über das
- * Vorhandensein eines generellen GEM-Traps (hier: '_crystal') im
- * verwendeten Entwicklungssystem macht, befindet sich im Quelltext in
- * 'BOXINPUT.S' und als Objektdatei im DRI-Format in 'BOXINPUT.O'.
- */
- int cdecl fsel_boxinput(char *path, char *name, int *button, char *label, FSEL_CALLBACK callback)
- { void *aespb[6], *addrin[6], *addrout[6];
- int contrl[5], global[15], intin[16], intout[7];
-
- aespb[0] = contrl;
- aespb[1] = global;
- aespb[2] = intin;
- aespb[3] = intout;
- aespb[4] = addrin;
- aespb[5] = addrout;
-
- contrl[0] = 91;
- contrl[1] = 0;
- contrl[2] = 2;
- contrl[3] = 4;
- contrl[4] = 0;
-
- addrin[0] = path;
- addrin[1] = name;
- addrin[2] = label;
- addrin[3] = callback;
-
- _crystal((AESPB *)aespb);
-
- *button = intout[1];
- return intout[0];
- }
-
- int main(void)
- { XDTA mydta;
- char path[130], name[34], outbuf[300];
- int exbtn, rv, d, i;
-
- appl_init();
- wind_get(0, WF_WORKXYWH, &xdesk, &ydesk, &wdesk, &hdesk);
-
- slct_cookie = (SLCT_STR *)get_cookie('FSEL');
-
- if ( !Supexec(setup_selector) )
- { form_alert(1, "[1][Kein kompatibler Fileselector|installiert.][ Ok ]");
- appl_exit();
- return 0;
- }
-
- Pdomain(1); /* Damit auch wirklich lange Namen rauskommen */
-
- /*
- * Ein Fenster hinter dem Fileselector öffenen, damit man sieht,
- * daß auch etwas beim Message-Callback ankommt.
- */
- window = wind_create(NAME | MOVER, xdesk, ydesk, wdesk, hdesk);
- if ( window < 0 )
- { form_alert(1, "[1][Das Fenster klemmt mal wieder!][ Ok ]");
- appl_exit();
- return 0;
- }
- wind_set(window, WF_NAME, "Noch'n Fenster");
- wind_open(window, xdesk + 50, ydesk + 50, 300, 200);
- window_redraw(window, xdesk, ydesk, wdesk, hdesk);
-
- getpath(path);
- strcat(path, "*.*");
- *name = 0;
- #if RETURN == 1
- do
- { Supexec(setup_selector);
- rv = fsel_boxinput(path, name, &exbtn, "BoxKite", &message_handler);
-
- if ( rv && exbtn )
- { Supexec(get_out_count);
- for ( i = 0; i < name_count; i++ )
- { sprintf(outbuf, "[1][Datei Nr: %d|%s][ Ok ]", i + 1, nameptrs[i]);
- form_alert(1, outbuf);
- }
- }
- }
- while ( rv && exbtn );
- #elif RETURN == 2
- do
- { Supexec(setup_selector);
- rv = fsel_boxinput(path, name, &exbtn, "BoxKite", &message_handler);
-
- if ( rv && exbtn )
- { sprintf(outbuf, "[1][%s][ Ok ]", stringbuf);
- form_alert(1, outbuf);
- }
- }
- while ( rv && exbtn );
- #else
- do
- { Supexec(setup_selector);
- rv = fsel_boxinput(path, name, &exbtn, "BoxKite", &message_handler);
- if ( rv && exbtn )
- { wind_update(BEG_UPDATE);
- d = p_get_first(&mydta, 0xff);
- i = 1;
- while( !d )
- { sprintf(outbuf, "[1][Datei Nr %d:|%s %02x][ Ok ]", i, mydta.d_fname, mydta.d_attrib);
- form_alert(1, outbuf);
- d = p_get_next(&mydta);
- i++;
- }
- p_release_dir();
- wind_update(END_UPDATE);
- }
- }
- while ( rv && exbtn );
- #endif
- wind_close(window);
- wind_delete(window);
- appl_exit();
- return 0;
- }
-